package com.biz.primus.ms.promotion.dao.po;

import com.biz.primus.model.promotion.enums.PromotionProductLimitTypeEnum;
import com.biz.primus.base.enums.PromotionTypeEnum;
import com.biz.primus.model.promotion.vo.OrderPromotionDetailVo;
import com.biz.primus.model.promotion.vo.req.OrderPromotionReqDetailVo;
import com.biz.primus.ms.base.jpa.converter.ListStringConverter;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Objects;
import javax.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 用户首单立减促销
 *
 * @author david-liu
 */
@Entity
@Getter
@Setter
public class UserFirstOrderCutPromotion extends BasePromotion {

    private static final long serialVersionUID = -6196248298785707828L;

    /**
     * 促销生效商品金额限制
      */
    private Integer productAmountLimit;

    // 减免金额
    @Column
    private Integer cutAmount;

    // 限制不能参与用户首单促销的方式(可选: 按分类, 按品牌, 按商品)
    @Enumerated(value = EnumType.STRING)
    private PromotionProductLimitTypeEnum productExcludeType;

    // 促销不能参与首单立减的分类ID
    @Convert(converter = ListStringConverter.class)
    @Column(columnDefinition = "TEXT")
    private List<Long> excludeCategoryIds;

    // 促销不能参与首单立减的品牌ID
    @Convert(converter = ListStringConverter.class)
    @Column(columnDefinition = "TEXT")
    private List<Long> excludeBrandIds;

    // 促销不能参与首单立减的商品ID
    @Convert(converter = ListStringConverter.class)
    @Column(columnDefinition = "TEXT")
    private List<Long> excludeProductIds;

    @Override
    public boolean isProductInPromotionLimit(OrderPromotionReqDetailVo detailVo) {
        detailVo.postProcess();
        if (Objects.isNull(this.getProductExcludeType())) {
            return true;
        }
        if (this.getProductExcludeType() == PromotionProductLimitTypeEnum.LIMIT_BY_CATEGORY) {
            return CollectionUtils.intersection(this.excludeCategoryIds, detailVo.getRequestCategoryIds()).size() < detailVo.getRequestCategoryIds().size();
        } else if (this.getProductExcludeType() == PromotionProductLimitTypeEnum.LIMIT_BY_BRAND) {
            return CollectionUtils.intersection(this.excludeBrandIds, detailVo.getRequestBrandIds()).size() < detailVo.getRequestBrandIds().size();
        } else {
            return CollectionUtils.intersection(this.excludeProductIds, detailVo.getRequestProductIds()).size() < detailVo.getRequestProductIds().size();
        }
    }

    /**
     * 判断传入的订单商品详情是否满足促销生效的条件
     *
     * @param detailVo 订单商品详情
     * @return boolean
     */
    @Override
    public boolean isMatchPromotionRule(OrderPromotionReqDetailVo detailVo) {
        detailVo.postProcess();
        if (Objects.isNull(this.getProductExcludeType())) {
            return detailVo.getTotalAmount() >= this.getProductAmountLimit();
        } else {
            int amount = 0;
            if (this.getProductExcludeType() == PromotionProductLimitTypeEnum.LIMIT_BY_CATEGORY) {
                for (Long categoryId : detailVo.getRequestCategoryIds()) {
                    boolean isCategoryMatched = CollectionUtils.isEmpty(this.getExcludeCategoryIds()) || (CollectionUtils.isNotEmpty(this.getExcludeCategoryIds()) && this.getExcludeCategoryIds().contains(categoryId));
                    if (isCategoryMatched) {
                        amount = amount + detailVo.getCategoryAmount(categoryId);
                    }
                }
            } else if (this.getProductExcludeType() == PromotionProductLimitTypeEnum.LIMIT_BY_BRAND) {
                for (Long brandId : detailVo.getRequestBrandIds()) {
                    boolean isBrandMatched = CollectionUtils.isEmpty(this.getExcludeBrandIds()) || (CollectionUtils.isNotEmpty(this.getExcludeBrandIds()) && this.getExcludeBrandIds().contains(brandId));
                    if (isBrandMatched) {
                        amount = amount + detailVo.getBrandAmount(brandId);
                    }
                }
            } else {
                for (Long productId : detailVo.getRequestProductIds()) {
                    boolean isProductMatched = CollectionUtils.isEmpty(this.getExcludeProductIds()) || (CollectionUtils.isNotEmpty(this.getExcludeProductIds()) && this.getExcludeProductIds().contains(productId));
                    if (isProductMatched) {
                        amount = amount + detailVo.getProductAmount(productId);
                    }
                }
            }
            return amount >= this.getProductAmountLimit();
        }
    }

    @Override
    public OrderPromotionDetailVo getOrderPromotionDetail(OrderPromotionReqDetailVo reqDetailVo) {
        reqDetailVo.postProcess();
        if (!isMatchPromotionRule(reqDetailVo)) {
            return null;
        }
        OrderPromotionDetailVo detailVo = new OrderPromotionDetailVo();
        detailVo.setId(this.getId());
        detailVo.setName(this.getName());
        detailVo.setDescription(this.getDescription());
        detailVo.setAllowCoupon(this.getAllowCoupon());
        detailVo.setPromotionType(PromotionTypeEnum.USER_FIRST_ORDER_CUT);
        detailVo.setEffectProductIds(this.getPromotionEffectProductIds(reqDetailVo));
        detailVo.setCutAmount(Math.max(this.cutAmount, 0));
        return detailVo;
    }

    @Override
    public List<Long> getPromotionEffectProductIds(OrderPromotionReqDetailVo reqDetailVo) {
        if (Objects.isNull(this.getProductExcludeType())) {
            return reqDetailVo.getRequestProductIds();
        } else {
            List<Long> effectProductIds = Lists.newArrayList();
            if (this.getProductExcludeType() == PromotionProductLimitTypeEnum.LIMIT_BY_CATEGORY) {
                for (Object o : CollectionUtils.removeAll(reqDetailVo.getRequestCategoryIds(), this.getExcludeCategoryIds())) {
                    Long categoryId = (Long) o;
                    effectProductIds.addAll(reqDetailVo.getRequestCategoryProductIds(categoryId));
                }
            } else if (this.getProductExcludeType() == PromotionProductLimitTypeEnum.LIMIT_BY_BRAND) {
                for (Object o : CollectionUtils.removeAll(reqDetailVo.getRequestBrandIds(), this.getExcludeBrandIds())) {
                    Long brandId = (Long) o;
                    effectProductIds.addAll(reqDetailVo.getRequestBrandProductIds(brandId));
                }
            } else {
                for (Object o : CollectionUtils.removeAll(reqDetailVo.getRequestProductIds(), this.getExcludeProductIds())) {
                    effectProductIds.add((Long) o);
                }
            }
            return effectProductIds;
        }
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
    }
}
